<template>
  <layout-content header="Deployments">
    <div style="float: left">
      <el-button
        v-has-permissions="{
          scope: 'namespace',
          apiGroup: 'apps',
          resource: 'deployments',
          verb: 'create'
        }"
        type="primary"
        size="small"
        @click="yamlCreate"
      >
        YAML
      </el-button>
      <el-button
        v-has-permissions="{
          scope: 'namespace',
          apiGroup: 'apps',
          resource: 'deployments',
          verb: 'create'
        }"
        type="primary"
        size="small"
        @click="onCreate"
      >
        {{ $t("commons.button.create") }}
      </el-button>
      <el-button
        v-has-permissions="{
          scope: 'namespace',
          apiGroup: 'apps',
          resource: 'deployments',
          verb: 'update'
        }"
        type="primary"
        size="small"
        :disabled="selections.length === 0"
        @click="onDeployScale()"
      >
        {{ $t("commons.button.scale") }}
      </el-button>
      <el-button
        v-has-permissions="{
          scope: 'namespace',
          apiGroup: 'apps',
          resource: 'deployments',
          verb: 'delete'
        }"
        type="primary"
        size="small"
        :disabled="selections.length === 0"
        @click="onDelete()"
      >
        {{ $t("commons.button.delete") }}
      </el-button>
    </div>
    <complex-table
      v-model:selects="selections"
      v-loading="uiState.loading"
      :data="deploymentList"
      :pagination-config="page"
      :search-config="listSearchQuery"
      @search="reloadDeployments"
    >
      <el-table-column type="selection" fix />
      <el-table-column
        :label="$t('commons.table.name')"
        prop="name"
        min-width="100"
        show-overflow-tooltip
      >
        <template #default="{ row }">
          <el-button link type="primary" @click="openDetail(row)">
            {{ row.metadata.name }}
          </el-button>
        </template>
      </el-table-column>
      <el-table-column
        :label="$t('business.namespace.namespace')"
        min-width="80"
        prop="metadata.namespace"
      />
      <el-table-column :label="$t('commons.table.status')" min-width="40">
        <template #default="{ row }">
          {{ row.status.readyReplicas || 0 }} / {{ row.status.replicas }}
        </template>
      </el-table-column>
      <el-table-column
        :label="$t('commons.table.created_time')"
        min-width="60"
        prop="metadata.creationTimestamp"
        fix
      >
        <template #default="{ row }">
          {{ row.metadata.creationTimestamp }}
        </template>
      </el-table-column>
      <ko-table-operations
        :buttons="uiState.options"
        :label="$t('commons.table.action')"
      />
    </complex-table>

    <el-dialog
      v-model="uiState.dialogScaleVisible"
      :title="$t('commons.button.scale')"
      width="30%"
      :close-on-click-modal="false"
    >
      <el-form
        ref="form"
        label-position="top"
        style="margin-left: 30px"
        :model="scaleCfg"
      >
        <div>
          <el-form-item
            :label="
              $t('business.common.basic') + '  (namespace / name / replicas)'
            "
          >
            <div v-for="(item, index) in selections" v-bind:key="index">
              <span>
                {{ item.metadata.namespace }} / {{ item.metadata.name }} *
                {{ item.spec.replicas }}
              </span>
            </div>
          </el-form-item>
          <el-form-item
            :label="$t('business.workload.replicas')"
            prop="replicas"
          >
            <ko-data-item
              v-model.number="scaleCfg.replicas"
              itemType="number"
            />
          </el-form-item>
        </div>
      </el-form>
      <template v-slot:footer>
        <div class="dialog-footer">
          <el-button size="small" @click="uiState.dialogScaleVisible = false">
            {{ $t("commons.button.cancel") }}
          </el-button>
          <el-button size="small" @click="onDeployScaleSubmit">
            {{ $t("commons.button.confirm") }}
          </el-button>
        </div>
      </template>
    </el-dialog>

    <el-dialog
      v-model="uiState.dialogModifyVersionVisible"
      :title="$t('commons.button.modifying_version')"
      width="70%"
      :close-on-click-modal="false"
    >
      <complex-table v-loading="uiState.loading" :data="imageRowList">
        <el-table-column
          :label="$t('business.workload.container_type')"
          prop="type"
          min-width="10"
        />
        <el-table-column
          :label="$t('business.workload.name')"
          prop="name"
          min-width="20"
          show-overflow-tooltip
        />
        <el-table-column
          :label="$t('business.workload.container_image')"
          prop="image"
          min-width="40"
          show-overflow-tooltip
        />
        <el-table-column
          :label="$t('business.workload.current_version')"
          prop="version"
          min-width="15"
        />
        <el-table-column
          :label="$t('business.workload.new_version')"
          prop="newVersion"
          min-width="20"
        >
          <template #default="{ row }">
            <ko-data-item v-model="row.newVersion" itemType="input" />
          </template>
        </el-table-column>
      </complex-table>
      <template v-slot:footer>
        <div class="dialog-footer">
          <el-button
            size="small"
            @click="uiState.dialogModifyVersionVisible = false"
          >
            {{ $t("commons.button.cancel") }}
          </el-button>
          <el-button size="small" @click="onModifyVersionSubmit">
            {{ $t("commons.button.confirm") }}
          </el-button>
        </div>
      </template>
    </el-dialog>
  </layout-content>
</template>

<script setup lang="ts">
import LayoutContent from "@/views/domain/kubeHud/views/components/layout/LayoutContent.vue";
import KoDataItem from "@/views/domain/kubeHud/views/components/ko-data-item/index.vue";
import ComplexTable from "@/views/domain/kubeHud/views/components/complex-table/index.vue";
import KoTableOperations from "@/views/domain/kubeHud/views/components/ko-table-operations/index.vue";
import { onMounted, reactive, ref } from "vue";
import { useI18n } from "vue-i18n";
import { checkPermissions } from "@/views/domain/kubeHud/utils/permission";
import { Deployment, useK8SApi } from "@/views/domain/kubeHud/api/k8s";
import { ElMessageBox, ElNotification } from "element-plus";
import { parseImage } from "@/views/domain/kubeHud/utils";
import { saveYamlAsFile } from "@/views/domain/kubeHud/utils/file";
import { KRouteDeployment } from "@/views/domain/kubeHud/router";
import { useVerifyRouter } from "@/router/use";
import { useBaseCRUDRoute } from "@/views/domain/kubeHud/api/provider/baseListProvider";

const { t } = useI18n();
const router = useVerifyRouter();
// import { scaleDeployment, patchDeployment } from "@/api/deployments";
// import {
//   listWorkLoads,
//   deleteWorkLoad,
//   getWorkLoadByName
// } from "@/api/workloads";
// import { downloadYaml } from "@/utils/actions";
// import { checkPermissions } from "@/utils/permission";

const { deploymentRepo } = useK8SApi();

type Prop = {
  clusterName?: string;
  namespace?: string;
};

const props = withDefaults(defineProps<Prop>(), {
  namespace: "default"
});

const editDeployment = ref<Deployment>();
type ImageRowType = {
  type?: string;
  name?: string;
  image?: string;
  version?: string;
  newVersion?: string;
};
const imageRowList = ref<ImageRowType[]>([]);

const page = ref({
  currentPage: 1,
  pageSize: 10,
  total: 0
});

const listSearchQuery = ref({
  keywords: ""
});

const { pushTo } = useBaseCRUDRoute({ router });

const uiState = reactive({
  loading: false,
  dialogModifyVersionVisible: false,
  dialogScaleVisible: false,
  options: [
    {
      label: t("commons.button.edit"),
      icon: "el-icon-edit",
      click: row => {
        pushTo(KRouteDeployment.Edit, {
          operation: "edit",
          namespace: row.metadata.namespace,
          name: row.metadata.name
        });
      },
      disabled: async () => {
        return await !checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "deployments",
          verb: "update"
        });
      }
    },
    {
      label: t("commons.button.scale"),
      icon: "el-icon-copy-document",
      click: row => {
        onDeployScale(row);
      },
      disabled: () => {
        return !checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "deployments",
          verb: "update"
        });
      }
    },
    {
      label: t("commons.button.modifying_version"),
      icon: "el-icon-edit-outline",
      click: row => {
        onModifyVersion(row);
      },
      disabled: async () => {
        return !(await checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "deployments",
          verb: "update"
        }));
      }
    },
    {
      label: t("commons.button.restart"),
      icon: "el-icon-refresh",
      click: row => {
        onRestartDeployment(row);
      },
      disabled: async () => {
        return !(await checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "deployments",
          verb: "update"
        }));
      }
    },
    {
      label: t("commons.button.edit_yaml"),
      icon: "el-icon-edit",
      click: row => {
        pushTo(KRouteDeployment.Edit, {
          operation: "edit",
          namespace: row.metadata.namespace,
          name: row.metadata.name,
          yaml: "true"
        });
      },
      disabled: async () => {
        return !(await checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "deployments",
          verb: "update"
        }));
      }
    },
    {
      label: t("commons.button.download_yaml"),
      icon: "el-icon-download",
      click: row => {
        saveDeploymentYamlToLocal(row);
      }
    },
    {
      label: t("commons.button.delete"),
      icon: "el-icon-delete",
      click: row => {
        onDelete(row);
      },
      disabled: () => {
        return !checkPermissions({
          scope: "namespace",
          apiGroup: "apps",
          resource: "deployments",
          verb: "delete"
        });
      }
    }
  ]
});

const scaleCfg = ref({
  replicas: 1
});

const deploymentList = ref<Deployment[]>([]);
const selections = ref<Deployment[]>([]);

const onCreate = () => {
  pushTo(KRouteDeployment.Create, {
    operation: "create",
    type: "Deployment"
  });
};
const openDetail = row => {
  pushTo(KRouteDeployment.Details, {
    namespace: row.metadata.namespace,
    name: row.metadata.name
  });
};

const yamlCreate = () => {
  pushTo(KRouteDeployment.Create, {
    type: "deployments",
    operation: "create"
  });
};
const onDelete = (row?: Deployment) => {
  ElMessageBox.alert(
    t("commons.confirm_message.delete"),
    t("commons.message_box.prompt"),
    {
      confirmButtonText: t("commons.button.confirm"),
      cancelButtonText: t("commons.button.cancel"),
      type: "warning"
    }
  ).then(() => {
    const deleteRows = [];
    if (row) {
      deleteRows.push(deploymentRepo.deleteDeployment({}, row));
    } else {
      if (selections.value.length > 0) {
        for (const select of selections.value) {
          deleteRows.push(deploymentRepo.deleteDeployment({}, select));
        }
      }
    }
    if (deleteRows.length !== 0) {
      Promise.all(deleteRows)
        .then(() => {
          reloadDeployments(true);
          ElNotification.success({
            type: "success",
            message: t("commons.msg.delete_success")
          });
        })
        .catch(() => {
          reloadDeployments(true);
        });
    }
  });
};

const reloadDeployments = async (resetPage?: boolean) => {
  selections.value = [];
  const { items } = await deploymentRepo.getDeploymentList({
    clusterName: props.clusterName
    // namespace: props.namespace
  });

  if (items) {
    deploymentList.value = items;
  }
};

const onRestartDeployment = (row: Deployment) => {
  uiState.loading = true;
  deploymentRepo
    .restartDeployment({
      clusterName: props.clusterName,
      namespace: row.metadata.namespace,
      name: row.metadata.name
    })
    .then(res => {})
    .finally(() => {
      uiState.loading = false;
    });
};

const onDeployScale = (deployItem?: Deployment) => {
  if (deployItem) {
    selections.value = [deployItem];
  }
  uiState.dialogModifyVersionVisible = true;
};
const saveDeploymentYamlToLocal = async (row: Deployment) => {
  deploymentRepo
    .getDeploymentDetail({
      cluster: props.clusterName,
      namespace: row.metadata.namespace,
      srcName: row.metadata.name
    })
    .then((res: any) => {
      if (res) {
        const dwObj = Object.assign({}, res);
        delete dwObj.ok;
        saveYamlAsFile(dwObj, `${row.metadata.name}.yaml`);
      }
    });
};

const onDeployScaleSubmit = () => {
  uiState.loading = true;
  Promise.all([
    selections.value.map(item => {
      return deploymentRepo.scaleDeployment({
        cluster: props.clusterName,
        namespace: item.metadata.namespace,
        name: item.metadata.name,
        data: Object.assign(item, {
          spec: { replicas: scaleCfg.value.replicas }
        })
      });
    })
  ])
    .then((res: any[]) => {
      const resOk = res.every(item => item.ok);
      if (resOk) {
        ElNotification.success({
          message: t("commons.msg.update_success")
        });
      } else {
        ElNotification.error({
          message: t("commons.msg.update_failed")
        });
      }
    })
    .finally(() => {
      uiState.loading = false;
    });
};

const onModifyVersion = (row: Deployment) => {
  imageRowList.value =
    row.spec?.template?.spec?.containers.map(c => {
      const imgVer = parseImage(c.image);
      return {
        name: c.name,
        type: "standardContainer",
        image: imgVer.image,
        version: imgVer.version,
        newVersion: imgVer.version
      };
    }) ?? [];

  imageRowList.value.push(
    ...(row.spec?.template?.spec?.initContainers.map(c => {
      const imgVer = parseImage(c.image);
      return {
        name: c.name,
        type: "initContainer",
        image: imgVer.image,
        version: imgVer.version,
        newVersion: imgVer.version
      };
    }) ?? [])
  );

  editDeployment.value = row;
  uiState.dialogModifyVersionVisible = true;
};

const onModifyVersionSubmit = () => {
  if (!editDeployment.value) return;
  uiState.loading = true;
  imageRowList.value.forEach(item => {
    if (item.type === "standardContainer") {
      editDeployment.value?.spec?.template?.spec?.containers?.forEach(
        container => {
          if (
            container.name === item.name &&
            item.newVersion !== item.version
          ) {
            container.image =
              item.image + (item.newVersion && item.newVersion !== "")
                ? item.newVersion
                : item.version;
          }
        }
      );
    } else if (item.type === "initContainer") {
      editDeployment.value?.spec?.template?.spec?.initContainers?.forEach(
        container => {
          if (
            container.name === item.name &&
            item.newVersion !== item.version
          ) {
            container.image =
              item.image + (item.newVersion && item.newVersion !== "")
                ? item.newVersion
                : item.version;
          }
        }
      );
    }
  });

  deploymentRepo
    .patchDeployment({
      cluster: props.clusterName,
      namespace: editDeployment.value.metadata.namespace,
      name: editDeployment.value.metadata.name,
      data: editDeployment.value
    })
    .then(({ ok }) => {
      ElNotification.success({
        title: ok
          ? t("commons.message_box.prompt")
          : t("commons.message_box.alert"),
        message: ok
          ? t("commons.msg.update_success")
          : t("commons.msg.update_failed"),
        position: "bottom-right"
      });
    })
    .finally(() => {
      uiState.loading = false;
      uiState.dialogModifyVersionVisible = false;
    });
};

onMounted(() => {
  reloadDeployments();
});
</script>
